﻿/*
COPYRIGHT (C) 2008 EPISERVER AB

THIS FILE IS PART OF WIKIX.
WIKIX IS FREE SOFTWARE: YOU CAN REDISTRIBUTE IT AND/OR MODIFY IT UNDER THE TERMS OF THE GNU LESSER GENERAL PUBLIC LICENSE VERSION v2.1 AS PUBLISHED BY THE FREE SOFTWARE FOUNDATION.

WIKIX IS DISTRIBUTED IN THE HOPE THAT IT WILL BE USEFUL, BUT WITHOUT ANY WARRANTY; WITHOUT EVEN THE IMPLIED WARRANTY OF MERCHANTABILITY OR FITNESS FOR A PARTICULAR PURPOSE. SEE THE GNU LESSER GENERAL PUBLIC LICENSE FOR MORE DETAILS.
YOU SHOULD HAVE RECEIVED A COPY OF THE GNU LESSER GENERAL PUBLIC LICENSE ALONG WITH WIKIX. IF NOT, SEE <HTTP://WWW.GNU.ORG/LICENSES/>.
*/

using System;
using System.Web.UI.HtmlControls;
using System.Xml;
using EPiServer.Common;
using EPiServer.Core;
using EPiServer.Core.Html;
using EPiServer.Templates.RelatePlus.Templates.PageEntity;
using EPiServer.Web;

namespace EPiServer.Research.Wiki.Core
{
    public class WikiPageBase : EPiServer.Templates.RelatePlus.Pages.Base.PageBase
    {
        #region Private Member variables
        private PageEntity _currentPageEntity;
        #endregion

        #region Properties
        public PageEntity CurrentPageEntity
        {
            get
            {
                if ((_currentPageEntity == null && ViewState["currentPageEntityGUID"] != null))
                {
                    _currentPageEntity = PageEntityHandler.GetPageEntityByGUID((Guid)ViewState["currentPageEntityGUID"]);
                }

                if (_currentPageEntity == null)
                {
                    _currentPageEntity = PageEntityHandler.GetPageEntityByGUID(CurrentPage.PageGuid);
                }

                if (CurrentPage.PageTypeName != WikiManager.WIKIROOTNAME && CurrentPage.PageTypeName != WikiManager.WIKIARTICLENAME)
                {

                    return null;
                    
                }
                // Uncomment this if you are working with several community sites.
                // check that current site has been inititalized and defined
                //if (SiteHandler.CurrentSite == null)
                //{
                //    throw new EPiServerException("Current site is null - cannot create Page Entity");
                //}

                // if still null create it
                if (_currentPageEntity == null)
                {
                    _currentPageEntity = (PageEntity)PageEntityHandler.AddPageEntity((PageEntity)Activator.CreateInstance(PageEntityUtils.GetPageEntityType(CurrentPage), CurrentPage.PageGuid, SiteHandler.CurrentSite));
     
                }
                return _currentPageEntity;
            }
            set
            {
                _currentPageEntity = value;
                ViewState["currentPageEntityGUID"] = (value != null) ? (object)value.PageGUID : null;
            }
        }

        /// <summary>
        /// Gets the feed count property.
        /// </summary>
        /// <value>The amount of items listed in the feed. Can be overridden by a page/dynamic property.</value>
        private int FeedCount
        {
            get
            {
                return Int32.MaxValue;
            }
        }

        /// <summary>
        /// The collection used for creating items for the feed. In this the base version, it is an empty collection. 
        /// Pages that inherit from this should override this property to define a relevant source for the feeds.
        /// </summary>
        /// <value>An empty PageDataCollection.</value>
        protected virtual PageDataCollection FeedSource
        {
            get
            {
                return new PageDataCollection();
            }
        }
        #endregion

        #region method overrides
        /// <summary>
        /// Checks the query string for a feed parameter. If the feed prameter equals "RSS" we generate an RSS 2.0 feed instead of the normal display.
        /// If the feed equals "Atom" we generate a Atom 1.0 feed instead of the normal display.
        /// </summary>
        /// <param name="e">An <see cref="T:System.EventArgs"></see> that contains the event data.</param>
        protected override void OnPreInit(EventArgs e)
        {
            if (String.Compare(Request["feed"], "RSS", true) == 0)
            {
                Response.ContentEncoding = System.Text.Encoding.UTF8;
                Response.ContentType = "text/xml";
                WriteRSS();
                Response.End();
            }
            else if (String.Compare(Request["feed"], "Atom", true) == 0)
            {
                Response.ContentEncoding = System.Text.Encoding.UTF8;
                Response.ContentType = "text/xml";
                WriteAtom();
                Response.End();
            }
        }

        /// <summary>
        /// Adds links for the RSS and Atom feed to the head section to make the avaliable for subscription.
        /// </summary>
        /// <param name="e">The <see cref="T:System.EventArgs"></see> object that contains the event data.</param>
        protected override void OnLoad(EventArgs e)
        {
            HtmlLink link = new HtmlLink();
            string url = CreateExternalLink(CurrentPage);
            string separator = "?";

            if (url.Contains("?"))
            {
                separator = "&";
            }

            link.Href = String.Format("{0}{1}feed=RSS", url, separator);
            link.Attributes.Add("rel", "alternate");
            link.Attributes.Add("type", "application/rss+xml");
            link.Attributes.Add("title", String.Format("RSS {0} ", CurrentPage.PageName));
            Header.Controls.Add(link);

            link = new HtmlLink();
            link.Href = String.Format("{0}{1}feed=Atom", url, separator);
            link.Attributes.Add("rel", "alternate");
            link.Attributes.Add("type", "application/atom+xml");
            link.Attributes.Add("title", String.Format("Atom {0} ", CurrentPage.PageName));
            Header.Controls.Add(link);

            this.RegisterScriptFile("~/Templates/WikiX/js/rollover.js");
            this.RegisterScriptFile("~/Templates/WikiX/js/jquery-1.3.1.js");
            this.RegisterScriptFile("~/Templates/WikiX/js/jquery.autocomplete.js");
            this.RegisterScriptFile("~/Templates/WikiX/js/jquery.filestyle.js");
            this.RegisterScriptFile("~/Templates/WikiX/js/jquery-ui-personalized-1.6rc6.min.js");

            PageData root = WikiManager.Instance.GetWikiRoot(CurrentPageLink);
            if (!CurrentPage.QueryDistinctAccess(EPiServer.Security.AccessLevel.Administer))
            {
                if (root["EditorRemoveRightClick"] != null)
                {
                    bool remove = (bool)root["EditorRemoveRightClick"];
                    if (remove)
                    {
                        WikiManager.Instance.RemoveRightClick((PageBase)Page);
                    }
                }
            }

            base.OnLoad(e);
        }

        /// <summary>
        /// Writes the RSS feed.
        /// </summary>
        protected virtual void WriteRSS()
        {
            XmlTextWriter writer = new XmlTextWriter(Response.OutputStream, System.Text.Encoding.UTF8);
            string url;
            PageData page;

            writer.WriteStartDocument();
            writer.WriteStartElement("rss");
            writer.WriteAttributeString("version", "2.0");
            writer.WriteAttributeString("xmlns:dc", "http://purl.org/dc/elements/1.1/");
            writer.WriteStartElement("channel");
            writer.WriteElementString("language", CurrentPage.LanguageID);
            writer.WriteElementString("title", CurrentPage.PageName);

            writer.WriteElementString("link", EPiServer.Configuration.Settings.Instance.SiteUrl.ToString());
            writer.WriteElementString("description", CurrentPage["Description"] as string);
            writer.WriteElementString("ttl", "60");
            writer.WriteElementString("generator", "EPiServer Wiki");

            for (int i = 0; i < FeedSource.Count && i < FeedCount; i++)
            {
                page = FeedSource[i];
                url = CreateExternalLink(page);
                writer.WriteStartElement("item");
                writer.WriteElementString("title", page.PageName);
                writer.WriteElementString("link", url);

                writer.WriteElementString("description", TextIndexer.StripHtml((String)page["MainBody"], 250));
                writer.WriteElementString("guid", url);
                writer.WriteElementString("pubDate", page.Changed.ToString("r"));

                foreach (int category in page.Category)
                {
                    writer.WriteElementString("category", page.Category.GetCategoryName(category));
                }
                writer.WriteEndElement();
            }

            writer.WriteEndElement();
            writer.WriteEndElement();
            writer.WriteEndDocument();

            writer.Close();
        }

        /// <summary>
        /// Writes the atom feed.
        /// </summary>
        protected virtual void WriteAtom()
        {
            XmlTextWriter writer = new XmlTextWriter(Response.OutputStream, System.Text.Encoding.UTF8);
            string url;
            PageData page;

            writer.WriteStartDocument();
            writer.WriteStartElement("feed");
            writer.WriteAttributeString("xmlns", "http://www.w3.org/2005/Atom");

            writer.WriteStartElement("title");
            writer.WriteAttributeString("type", "text");
            writer.WriteValue(CurrentPage.PageName);
            writer.WriteEndElement();

            writer.WriteStartElement("link");
            writer.WriteAttributeString("href", EPiServer.Configuration.Settings.Instance.SiteUrl.ToString());
            writer.WriteEndElement();

            writer.WriteElementString("updated", DateTime.Now.ToUniversalTime().ToString("o"));
            writer.WriteElementString("id", CreateExternalLink(CurrentPage));

            writer.WriteStartElement("generator");
            writer.WriteAttributeString("uri", EPiServer.Configuration.Settings.Instance.SiteUrl.ToString());
            writer.WriteAttributeString("version", "1.0");
            writer.WriteValue("EPiServer Wiki");
            writer.WriteEndElement();

            for (int i = 0; i < FeedSource.Count && i < FeedCount; i++)
            {
                page = FeedSource[i];
                url = CreateExternalLink(page);
                writer.WriteStartElement("entry");
                writer.WriteElementString("title", page.PageName);

                writer.WriteStartElement("link");
                writer.WriteAttributeString("href", url);
                writer.WriteEndElement();

                writer.WriteElementString("id", url);
                writer.WriteElementString("updated", page.Changed.ToUniversalTime().ToString("o"));

                writer.WriteElementString("summary", TextIndexer.StripHtml((String)page["MainBody"], 250));

                writer.WriteEndElement();
            }

            writer.WriteEndElement();
            writer.WriteEndDocument();

            writer.Close();
        }
        #endregion

        /// <summary>
        /// Create a string with an absolute link to the page. Checks if furl is enabled and rewrites the link if appropriate.
        /// </summary>
        /// <param name="page">A PageData to create an absolute link from.</param>
        /// <returns>An absolute link to page</returns>
        public string CreateExternalLink(PageData page)
        {
            UrlBuilder url = new UrlBuilder(page.LinkURL);

            if (UrlRewriteProvider.IsFurlEnabled && PermanentLinkUtility.IsMappableUrl(url))
            {
                Global.UrlRewriteProvider.ConvertToExternal(url, null, System.Text.UTF8Encoding.UTF8);
                return UriSupport.Combine(EPiServer.Configuration.Settings.Instance.SiteUrl.ToString(), url.ToString());
            }


            return url.ToString();

        }
        
    }
}
